#pragma once
#include "datamanager.hpp"
#include "httplib.h"
#include <ctime>
namespace Cloud
{
#include <utime.h>
    std::string timeToStr(time_t time)
    {
        char str[100]{};
        ctime_r(&time, str);
        return str;
    }
    std::string getETag(FileInfo fileInfo)
    {
        return fileInfo._url + std::to_string(fileInfo._mtime);
    }
    class Service
    {
    public:
        Service()
            : _serverPort(Config::getInstance()->getServerPort()),
              _serverIp(Config::getInstance()->getServerIp()),
              _downloadPrefix(Config::getInstance()->getDownloadPrefix()),
              _server() {}

        bool run()
        {
            std::cout << "run" << std::endl;

            _server.Get("/", show);
            _server.Get("/show", show);
            _server.Get("/onlineupload", showOnlineupload);
	        _server.Get("/success", showSuccess);
            _server.Get(_downloadPrefix + "(.*)", download);
            _server.Post("/upload", upload);

            std::cout << "begin listen" << std::endl;
            _server.listen("0.0.0.0", Config::getInstance()->getServerPort());
            std::cout << "listen over" << std::endl;
            return true;
        }
        static void upload(const httplib::Request &req, httplib::Response &rsp)
        {
            std::cout << "get a upload request\n";
            if (req.has_file("uploadFile") == false)
            {
                std::cout << "no file upload\n";
                rsp.status = 400;
                return;
            }
            const auto &file = req.get_file_value("uploadFile");
            
	        std::string backPath = Config::getInstance()->getBackDir() + file.filename;
	        std::cout << backPath << std::endl;
	    
	        rsp.body.clear();
            FileUtils(backPath).setContent(file.content);
            DataManager::getInstance()->insert(FileInfo(backPath)); // 这个顺序不能反
            rsp.set_header("Location", "/success");
            rsp.status = 302;
        }
        static void show(const httplib::Request &req, httplib::Response &rsp)
        {
            std::stringstream ss;
            ss << R"(<!DOCTYPE html><html><head><meta charset="UTF-8"><title>Download Page</title><style>body{font-family:Arial,sans-serif;background-color:#f4f4f4;margin:0;padding:0}header{background-color:#007BFF;color:#fff;text-align:center;padding:20px 0;box-shadow:0 2px 5px rgba(0,0,0,.1)}h1{margin:0;font-size:36px}.container{width:80%;margin:30px auto;padding:20px;background-color:#fff;box-shadow:0 4px 8px rgba(0,0,0,.1);border-radius:8px}table{width:100%;table-layout:fixed;border-collapse:collapse;margin-top:20px}th,td{padding:12px;text-align:right;border-bottom:1px solid #ddd;word-wrap:break-word}th{background-color:#f2f2f2;color:#333;font-size:18px}td{font-size:16px}td.file-info{text-align:right;color:#888}a{text-decoration:none;color:#fff;background-color:#28a745;padding:10px 15px;border-radius:5px;font-weight:bold;display:inline-block;text-align:center;transition:background-color .3s ease}a:hover{background-color:#218838}th:nth-child(1),td:nth-child(1),th:nth-child(2),td:nth-child(2),th:nth-child(3),td:nth-child(3),th:nth-child(4),td:nth-child(4){width:25%}@media(max-width:768px){.container{width:95%}h1{font-size:28px}td{font-size:14px}a{padding:8px 12px;font-size:14px}}</style></head><body><header><h1>Download Your File</h1></header><div class="container"><table><thead><tr><th>File Name</th><th>Last Modified</th><th>Size</th><th>Action</th></tr></thead><tbody>)";
            std::vector<FileInfo> arr;
            DataManager::getInstance()->getFileInfo(&arr);
            for (const auto &fileInfo : arr)
            {
                ss << "<tr>";
                ss << "<td>" << FileUtils(fileInfo._backPath).getFileName() << "</td>";
                ss << "<td>" << timeToStr(fileInfo._atime) << "</td>";
                ss << "<td>" << fileInfo._fsize / 1024 << "k</td>";
                ss << "<td><a href='" << fileInfo._url << "'>Download</a></td>";
                ss << "</tr>";
            }
            ss << R"(</tbody></table></div></body></html>)";
            rsp.set_content(ss.str(), "text/html");
            rsp.status = 200;
        }
        static void showOnlineupload(const httplib::Request &req, httplib::Response &rsp)
        {
            std::stringstream ss;
            ss << R"(<!DOCTYPE html><html lang="zh"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>文件上传</title><style>body {font-family: Arial, sans-serif; background-color: #f4f7fb; margin: 0; padding: 0; display: flex; justify-content: center; align-items: center; height: 100vh;} .upload-container {background-color: white; padding: 30px; border-radius: 8px; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); text-align: center; width: 100%; max-width: 400px;} .upload-container h2 {font-size: 24px; margin-bottom: 20px;} .upload-container p {font-size: 16px; color: #666; margin-bottom: 20px;} .file-input {margin: 20px 0; padding: 15px; width: 100%; border: 2px solid #007bff; border-radius: 5px; background-color: #f9f9f9; cursor: pointer; font-size: 16px; color: #333; box-sizing: border-box;} .file-input:hover {background-color: #e7f0ff; border-color: #0056b3;} .submit-button {padding: 10px 20px; background-color: #007bff; border: none; border-radius: 5px; color: white; font-size: 16px; cursor: pointer; transition: background-color 0.3s;} .submit-button:hover {background-color: #0056b3;}</style></head><body><div class="upload-container"><h2>上传文件</h2><p>请选择您要上传的文件，支持多种格式。</p><form action="http://113.44.51.126:8899/upload" method="post" enctype="multipart/form-data"><input type="file" name="uploadFile" class="file-input" required><br><input type="submit" value="上传" class="submit-button"></form></div></body></html>)";
            rsp.set_content(ss.str(), "text/html");
            rsp.status = 200;
        }
        static void download(const httplib::Request &req, httplib::Response &rsp)
        {
            std::cout << "get a download request\n";
            FileInfo fileInfo;
            if (DataManager::getInstance()->getInfoByURL(req.path, &fileInfo) == false)
            {
                std::cout << "request file not exist\n";
                return;
            }
            if (fileInfo._isPacked)
            {
                std::cout << "file isPacked, decompress to : " << fileInfo._backPath << std::endl;
                FileUtils(fileInfo._packPath).deCompress(fileInfo._backPath);
                fileInfo._isPacked = false;
                DataManager::getInstance()->update(fileInfo);
                FileUtils(fileInfo._packPath).remove(); // 这个记得加
            }

            // if(!std::ifstream(fileInfo._backPath))
            //     std::cerr << "open file to update atime error\n";

            // std::ifstream file(fileInfo._backPath);
            // if (file)
            // {
            //     file.close();
            //     // 如果你需要强制同步 atime，使用 fsync
            //     int fd = open(fileInfo._backPath.c_str(), O_RDONLY);
            //     if (fd != -1)
            //     {
            //         fsync(fd);  // 确保元数据更新
            //         close(fd);
            //     }
            // }

            // struct utimbuf new_times;
            // new_times.actime = time(NULL);  // 设置新的 atime，使用当前时间
            // new_times.modtime = fileInfo._mtime;
            struct utimbuf new_times = {time(NULL), fileInfo._mtime};
        
            if (utime(fileInfo._backPath.c_str(), &new_times) == -1)
                std::cerr << "atime update error!\n";
            else
                std::cout << "atime update success!\n";

            std::string eTag = getETag(fileInfo);

            bool isRange = false;
            if(req.has_header("If-Range"))
            {
                std::string clientETag = req.get_header_value("If-Range");
                if(eTag == clientETag)
                {
                    isRange = true;
                }
            }

            FileUtils(fileInfo._backPath).getContent(&rsp.body);
            rsp.set_header("Accept-Ranges", "bytes"); // 用来支持断点续传的
            rsp.set_header("ETag", eTag);             // 唯一标识
            rsp.set_header("Content-Type", "application/octet-stream");
            rsp.status = isRange ? 206 : 200;
        }
        static void showSuccess(const httplib::Request &req, httplib::Response &rsp)
        {
            std::stringstream ss;
            ss << R"(<!DOCTYPE html><html lang="zh"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>上传成功</title><style>body {font-family: Arial, sans-serif; background-color: #f4f7fb; margin: 0; padding: 0; display: flex; justify-content: center; align-items: center; height: 100vh;} .success-container {background-color: white; padding: 30px; border-radius: 8px; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); text-align: center; width: 100%; max-width: 400px;} .success-container h2 {font-size: 24px; margin-bottom: 20px;} .success-container p {font-size: 16px; color: #666; margin-bottom: 20px;} .home-button {padding: 10px 20px; background-color: #007bff; border: none; border-radius: 5px; color: white; font-size: 16px; cursor: pointer; transition: background-color 0.3s;} .home-button:hover {background-color: #0056b3;}</style></head><body><div class="success-container"><h2>上传成功！</h2><p>您的文件已经成功上传。</p></div></body></html> )";
	    rsp.set_content(ss.str(), "text/html");
            rsp.status = 200;
        }

    private:
        int _serverPort;
        std::string _serverIp;
        std::string _downloadPrefix;
        httplib::Server _server;
    };
}

